package com.yanyeori.framework.configencrypt.config;

import com.yanyeori.framework.core.util.AESUtil;
import com.yanyeori.framework.core.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

/**
 * 配置属性加解密
 *
 * @author chenkuan 2020/8/4
 */
@Slf4j
@Order
public class ConfigEncryptAutoConfig implements EnvironmentPostProcessor {
    /**
     * 配置加密启用开关.
     */
    private static final String CONFIGENCRYPT_ENABLE = "configencrypt.enable";

    /**
     * 加密属性列表
     */
    private static final String CONFIGENCRYPT_PROPS = "configencrypt.props";

    /**
     * 加密属性列表分割符
     */
    private static final String CONFIGENCRYPT_PROPS_SEPARATOR = ",";

    /**
     * 加解密秘钥
     */
    private static final String CONFIGENCRYPT_KEY = "configencrypt.key";

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication application) {
        try {
            //是否启用配置加密
            Boolean configEncryptEnable = env.getProperty(CONFIGENCRYPT_ENABLE, Boolean.class);
            if (!Boolean.TRUE.equals(configEncryptEnable)) {
                return;
            }
            //获取加解密秘钥
            String secretKey = env.getProperty(CONFIGENCRYPT_KEY, String.class);
            if (StringUtil.isEmpty(secretKey)) {
                return;
            }
            //获取加密属性列表(多个用英文逗号,隔开)
            String configEncryptProp = env.getProperty(CONFIGENCRYPT_PROPS);
            if (StringUtil.isEmpty(configEncryptProp)) {
                return;
            }
            List<String> configEncryptProps;
            int index = configEncryptProp.indexOf(CONFIGENCRYPT_PROPS_SEPARATOR);
            if (index == -1) {
                configEncryptProps = Collections.singletonList(configEncryptProp);
            } else {
                configEncryptProps = Arrays.asList(configEncryptProp.split(CONFIGENCRYPT_PROPS_SEPARATOR));
            }
            //加载所有配置
            MutablePropertySources propertySources = env.getPropertySources();
            for (PropertySource<?> propertySource : propertySources) {
                Properties properties = (Properties) propertySource.getSource();
                //判断是否存在配置的加密属性，存在则解密
                for (String encryptProp : configEncryptProps) {
                    if (StringUtil.isBlank(encryptProp)) {
                        continue;
                    }
                    encryptProp = encryptProp.trim();
                    String prop = properties.getProperty(encryptProp);
                    if (prop == null || prop.length() == 0) {
                        continue;
                    }
                    //解密并回写配置
                    prop = AESUtil.decrypt(prop, secretKey);
                    properties.setProperty(encryptProp, prop);
                }
            }
        } catch (Exception e) {
            log.error("Configencrypt init failed. caused by :", e);
        }
    }
}
